module Oos4ruby
  
=begin rdoc
  This class wraps feed response. You must use its subclass, Oos4ruby::Sites, Oos4ruby::Contacts, Oos4ruby::Medias
  
  API feed response is paginated, so, this class provides some methods to explore the feed.
=end
class Collection < Array
  
  def initialize(feed, auth, slug = nil)
    @feed = feed
    @auth = auth
    @slug = slug
    evalued_class = eval(self.class.name.gsub(/s$/, ''))
    @feed.entries.each {|entry| self << evalued_class.new(entry, @auth, @slug) }    
  end
 
=begin rdoc
  returns true if next page exists into the feed
=end  
  def next_page?
    @feed.next?
  end
  
=begin rdoc
  returns true if previous page exists into the feed
=end
  def previous_page?
    @feed.previous?
  end
  
=begin rdoc
  returns the next feed as a new Collection subclass.
=end
  def next_page    
    return get_page(@feed.next) if next_page?
  end
  
=begin rdoc
  returns the previous feed as a new Collection subclass.
=end
  def previous_page
    return get_page(@feed.previous) if previous_page?   
  end
  
=begin rdoc
  updats the current Collection with the next feed response.
=end
  def next_page!
    return get_page!(@feed.next)
  end
  
=begin rdoc
  updates the current Collection with the precious feed response.
=end
  def previous!
    return get_page!(@feed.previous)
  end

=begin rdoc
  returns the total size of the feed.
=end
  def total_size
    return @feed.total_size
  end
  
=begin rdoc
  return all entries into the feed.
=end
  def all
    all = self.to_a
    aux = self
    while aux.next_page?
      next_page = aux.next_page
      next_page.each {|entry| all << entry}
      aux = next_page
    end
    return all
  end
    
=begin rdoc
  reload the current collection
=end
  def refresh!
    return get_page!(@feed.self_link)
  end
  
  def to_s
    @entries.join("\n")
  end
  
=begin rdoc
  method to create a resource into a collection.
  opts available keys:
  * if you want to create a Site:
        :id => 11870 service/place id if it already exists in 11780
        if the service/place doesn't exit in 11870 then
          :title => service/place name (required)
          :user_address (required)
          :url (optional)
          :telephone (optional)
          :locality => a hash with :name and :slug (required)
          :country => a hash with :name and :slug (required)
        :summary => review title
        :content or :review_content => review_content
        :privacy => a REXML::Element from 11870 privacy scheme or one of the next strings => "public", "trustedContacts", "contacts", "private"
        :tags => an array of tags
        :lists => an array of lists
  * if you want to create a Contact:
        :contact or :slug or :title => the new contact slug
        :trusted => a REXML::Element from 11870 trusted scheme or a string with "true" or "false"
  * if you want to create a Media:
        :file => the new media file system path or a File object
        :content_length => file size
        :content_type => file content type
=end
  def create!(opts = {})    
    evalued_class = eval(self.class.name.gsub(/s$/, ''))
    body = evalued_class.dump! opts, @slug
    unless self.instance_of?Medias      
      body = "<?xml version='1.0' ?>\n" + body.to_s      
    end
    
    poster = HTTPInvoker.new( @feed.self_link, @auth)
    
    content_type = opts[:content_type] || AtomEntryContentType
    opts.reject {|k, v| k == :content_type}
    opts.each {|k, v| poster.set_header(k, v)}
    
    worked = poster.post content_type, body
        
    raise RuntimeError.new unless worked
    return evalued_class.new(poster.entry, @auth, @slug)
  end
=begin rdoc
  return true if the text of the element is equals to the given value

  i.e: 
    user.contacts.contains? 'oos:slug', 'calavera'
    user.sites.contains? 'oos:locality', 'Madrid'
=end
  def contains?(elem, value)
    self.each do |obj|
       if obj.contains?(elem, value)
         return true
       end
    end
    return false
  end
  
  private
  def get_page(link)
    getter = HTTPInvoker.new(link, @auth) 
    worked = getter.get
      
    return convert(getter.body) if worked
  end
  
  def get_page!(link)
    getter = HTTPInvoker.new(link, @auth)
    worked = getter.get
    if worked
      @feed = Feed.read(getter.body)
      convert(getter.body)
      return self
    end
  end
  
  def convert( body )
    evalued_class = eval(self.class.name)
    return evalued_class.new( Feed.read( body ), @auth, @slug )    
  end
  
end
end


